#include<iostream>
using namespace std;

/**
 * c++内存模型
 * 同时熟悉下static对函数内部变量的生命周期提升
 * 问题：
 *      了解下static在文件作用域中的变量的提升！就是不同c文件中同名称的static变量的相互关系！
 * 预告：
 *      下一节专门讲C语言中的static变量，静态变量，静态全局变量，静态局部变量
 * */

/**
 * 在C++中内存按照存储不同被划分了四个区域
 * 代码区域
 *      编译后的二进制代码，操作系统管理
 * 全局区域
 *      全局变量、静态变量和常量在这个区域存储
 * 栈区
 *      编译器自动分配，比如函数的形参，函数内部的局部变量，进入函数分配，所谓的压栈，退出函数自动释放，所谓的出栈
 *      栈区是先进先出
 * 堆区
 *      程序员自主控制的区域，一般通过new，或者c中的malloc, calloc,relloc创建，通过delete,或者c的free进行释放，只new不delete会有内存泄露
 *      高性能服务程序中通常会出现这种用法：
 *          程序启动的时候程序员会主动申请一块很大的内存区域，这样就避难了频繁的向操作系统申请和释放内存的耗时以提高性能
 *          然后程序员自主管理这块内存区域的数据更新维护，这时候就会要求有合理管理内存空间的一个策略，学习下这个课题！
 *          这个课题是高性能程序在内存方便节省时间的一个常见思路
 * */

int func1(int a, int b){
    //这里的a,b,都在栈区存储，进入函数分配a,b,c的空间，所谓的压栈，
    int c = 0;
    c = a + b;
    return c;
}

int func2(){
    static int istatic = 9;
    //这里的istatic存储在全局区域，变量一旦被static修饰，就会主动提升其生命周期为全局，即使函数退出，他还是存在的，再次进入函数，值还是上次访问时的值
    //这个可以通过多次调用函数，并且观察变量的内存地址就能确认

    //注意：这里只是提升了static变量的生命周期，但是作用域还是限定在函数内部，出了此函数就不再能够访问
    //      在全局区他的命名估计是这样的：func2_istatic; 这个阅读下《编译原理》求证下

    //观察下istatic的内存地址：
    cout << "在func2函数中istatic的地址：" << &istatic << endl;
    cout << "在func2函数中istatic的值：" << istatic << endl;

    return istatic;
}

int func3(){
    static int istatic = 10;

    //观察下istatic的内存地址：
    cout << "在func3函数中istatic的地址：" << &istatic << endl;
    cout << "在func3函数中istatic的值：" << istatic << endl;
    
    return istatic;
}

int main() {

    int i = func2();
    //这里先压栈i
    //然后进入func2,执行完讲func2返回的结果赋值给i变量，值拷贝形式
    cout << "i的地址：" << &i << endl;
    cout << i << endl;

    func3();
    func2();
    func3();

    return 0;
}
/**
 * $ ./test
在func2函数中istatic的地址：0x442000
在func2函数中istatic的值：9
i的地址：0x28cd34
9
在func3函数中istatic的地址：0x442004
在func3函数中istatic的值：10
在func2函数中istatic的地址：0x442000
在func2函数中istatic的值：9
在func3函数中istatic的地址：0x442004
在func3函数中istatic的值：10
*/
